home *** CD-ROM | disk | FTP | other *** search
- ; $Id: d_map.pro,v 1.25 1997/04/24 23:32:25 dave Exp $
- ;
- ; Copyright (c) 1997, Research Systems, Inc. All rights reserved.
- ; Unauthorized reproduction prohibited.
- ;
- ;+
- ; FILE:
- ; d_map.pro
- ;
- ; CALLING SEQUENCE: d_map
- ;
- ; PURPOSE:
- ; Shows the mapping features in IDL 5.0.
- ;
- ; MAJOR TOPICS: Visualization and maps
- ;
- ; CATEGORY:
- ; IDL 5.0
- ;
- ; INTERNAL FUNCTIONS and PROCEDURES:
- ; fun MenuToggleState - Toggle off and on state of a button
- ; fun Map_Menu_Choice - Handle the menu bar selection button
- ; pro MenuCreate - Create the menu bar
- ; pro Map_Demo_Color - Initialize working colors
- ; pro drawcirc - Draw a great circle
- ; pro cir2p - Connect 2 points with a great circle
- ; fun city_mark - Mark a city
- ; pro d_map_Event - Event handler
- ; pro d_map_Cleanup - Cleanup
- ; pro d_map - Main procedure
- ;
- ; EXTERNAL FUNCTIONS, PROCEDURES, and FILES:
- ; pro gettips - Read the tip file
- ; pro widtips - Create the tip widgets
- ; pro sizetips - Size the tip widgets
- ; pro puttips - Change a tips text
- ; map_demo.txt
- ; map_demo.tip
- ; cities.dat
- ; worldelv.dat
- ;
- ; REFERENCE: IDL Reference Guide, IDL User's Guide
- ;
- ; NAMED STRUCTURES:
- ; none.
- ;
- ; COMMON BLOCKS:
- ; MAP_DEMO_COM
- ;
- ; MODIFICATION HISTORY:
- ; 3/97, DMS - Written.
- ;-
- ;----------------------------------------------------------------------------
- ;
- ; PURPOSE Toggle the off and on state of a menu button
- ;
- Function MenuToggleState, $
- wid ; IN: widget identifier
-
- WIDGET_CONTROL, wid, GET_VALUE=name
-
- s = STRPOS(name, '(Off)')
- ret = s ne -1 ;TRUE if new state is on
- if ret then strput, name, '(On )', s $
- else strput, name, '(Off)', strpos(name, '(On )')
- WIDGET_CONTROL, wid, SET_VALUE=name
- RETURN, ret
- end ; of Toggle_state,
-
- ;----------------------------------------------------------------------------
- ;
- ; PURPOSE Given a uservalue from a menu button created
- ; by MenuCreate, return the index of the choice
- ; within the category. Set the selected menu button
- ; to insensitive to signify selection, and set all
- ; other choices for the category to sensitive.
- ;
- function Map_menu_choice, $
- Eventval, $ ; IN: uservalue from seleted menu button
- MenuItems, $ ; IN: menu item array, as returned by MenuCreate
- MenuButtons ; IN: button array as returned by MenuCreate
-
-
- i = STRPOS(eventval, '|', 0) ;Get the name less the last qualifier
- while (i GE 0) do begin
- j = i
- i = STRPOS(eventval, '|', i+1)
- endwhile
-
- base = STRMID(eventval, 0, j+1) ; Get the common buttons, includes last | .
- buttons = WHERE(STRPOS(MenuItems, base) EQ 0) ; buttons that share base name.
- this = (WHERE(eventval EQ MenuItems))(0) ; Get the Index of the selected item.
- for i=0, N_ELEMENTS(buttons)-1 do begin ;Each button in this category
- index = buttons(i)
- WIDGET_CONTROL, MenuButtons(buttons(i)), $
- SENSITIVE=index NE this
- endfor
-
- RETURN, this - buttons(0) ; Return the selected button's index.
- end
-
- ;----------------------------------------------------------------------------
- ;
- ; PURPOSE Create a menu from a string descriptor (MenuItems).
- ; Return the parsed menu items in MenuItems (overwritten),
- ; and the array of corresponding menu buttons in MenuButtons.
- ;
- ; MenuItems = (input/output), on input the menu structure
- ; in the form of a string array. Each button
- ; is an element, encoded as follows:
- ;
- ; Character 1 = integer bit flag. Bit 0 = 1 to denote a
- ; button with children. Bit 1 = 2 to denote
- ; this is the last child of its parent.
- ; Bit 2 = 4 to show that this button should
- ; initially be insensitive, to denote selection.
- ; Any combination of bits may be set.
- ; On RETURN, MenuItems contains the fully
- ; qualified button names.
- ;
- ; Characters 2-end = Menu button text. Text should NOT
- ; contain the character |, which is used
- ; to delimit menu names.
- ;
- ; Example:
- ;
- ; MenuItems = ['1File', '0Save', '2Quit', $
- ; '1Edit', '3Cut', $
- ; '3Help']
- ;
- ; Creates a menu with three top level buttons
- ; (file, edit and help). File has 2 choices
- ; (save and exit), Edit has one choice, and help has none.
- ; On RETURN, MenuItems contains the fully qualified
- ; menu button names in a string array of the
- ; form: ['<Prefix>|File', '<Prefix>|File|Save',
- ; '<Prefix>|File|Quit', '<Prefix>|Edit',..., etc. ]
- ;
- pro MenuCreate, $
- MenuItems, $ ; IN/OUT: See below
- MenuButtons, $ ; OUT: Button widget id's of the created menu
- Bar_base, $ ; IN: menu base ID
- Prefix=prefix ; IN: (opt) Prefix for this menu's button names.
- ; If omitted, no prefix
-
- level = 0
- parent = [ bar_base, 0, 0, 0, 0, 0]
- names = STRARR(5)
- lflags = INTARR(5)
-
- MenuButtons = LONARR(N_ELEMENTS(MenuItems))
-
- if (N_ELEMENTS(prefix)) then begin
- names(0) = prefix + '|'
- endif else begin
- names(0) = '|'
- endelse
-
- for i=0, N_ELEMENTS(MenuItems)-1 do begin
- flag = FIX(STRMID(MenuItems(i), 0, 1))
- txt = STRMID(MenuItems(i), 1, 100)
- uv = ''
-
- for j = 0, level do uv = uv + names(j)
- MenuItems(i) = uv + txt ; Create the button for fully qualifid names.
- isHelp = txt eq 'Help' or txt eq 'About'
- MenuButtons(i) = WIDGET_BUTTON(parent(level), $
- VALUE= txt, UVALUE=uv+txt, $
- MENU=flag and 1, HELP=isHelp)
-
- if ((flag AND 4) NE 0) then begin
- WIDGET_CONTROL, MenuButtons(i), SENSITIVE = 0
- endif
-
- if (flag AND 1) then begin
- level = level + 1
- parent(level) = MenuButtons(i)
- names(level) = txt + '|'
- lflags(level) = (flag and 2) NE 0
- endif else if ((flag AND 2) NE 0) then begin
- while lflags(level) do level = level-1 ; Pops the previous levels.
- level = level - 1
- endif
- endfor
- end
-
- ;----------------------------------------------------------------------------
- ;
- ; PURPOSE Initialize the working colors.
- ;
- pro map_demo_color, base
-
- common colors, r_orig, g_orig, b_orig, r_curr, g_curr, b_curr
-
-
- nc = !d.table_size < 256 > 16 ;# of colors we use
-
- if (N_ELEMENTS(r_orig) NE nc) then begin
- r_orig = BYTARR(nc)
- g_orig = BYTARR(nc)
- b_orig = BYTARR(nc)
- endif
-
- ; Define interpolation points:
- ; (elevation in meters, r, g, b) be sure elevation of 1st element is
- ; -5000 (data value 0), and last is 5240 (data value 256).
- ; With this scaling, sea level is ~ 125.
-
- c = FLTARR(256, 3)
-
- nelev = nc - base ;# of color for elevations
-
- ; Elev Red Green Blue
- p = [[ -5000, 64, 64, 64], $ ; Dark Gray at 0
- [ -4900, 0, 0, 128], $ ; Dim blue
- [ -1500, 0, 0, 255], $ ; Bright blue
- [ -40, 192, 192, 255], $ ; Brownish
- [ 0, 64, 192, 64], $ ; Med green
- [ 250, 150, 150, 75], $ ; Dim Yellow
- [ 1000, 200, 200, 100], $ ; Brighter yellow
- [ 4000, 255, 255, 255], $ ; White
- [ 5240, 255, 255, 255]] ; To white
-
- n = N_ELEMENTS(p)/4
-
- for i=0,n-2 do begin ;Each interpolation interval
- s0 = (p(0,i)+5000) * nelev / (256 * 40)
- s1 = (p(0,i+1)+5000) * nelev / (256 * 40)
- m = s1 - s0
- if m gt 0 then for j=0,2 do begin ; Loop over each color.
- s = FLOAT(p(j+1,i+1) - p(j+1,i)) / m
- c(s0, j) = FINDGEN(m) * s + p(j+1,i)
- endfor
- endfor
-
- TEK_COLOR, 0, base ;Load original tektronix color table.
- r_orig(base) = BYTE(c(0:nelev-1,0))
- g_orig(base) = BYTE(c(0:nelev-1,1))
- b_orig(base) = BYTE(c(0:nelev-1,2))
- r_curr = r_orig
- g_curr = g_orig
- b_curr = b_orig
- TVLCT,r_orig, g_orig, b_orig
- end
-
- ;----------------------------------------------------------------------------
- ;
- ; PURPOSE Draw a great circle with given rotation and offset.
- ;
- pro drawcirc, $
- rot, $ ; IN: rotation angle (in degrees)
- lon0, $ ; IN: longitude
- color ; IN: color of the great circle
-
- n = 180 ;Use 180 points
- rota = rot * !DTOR ;Radians
-
- t = FINDGEN(n+1) * (2 * !PI/n)
- sint = SIN(t)
- y = COS(t)
- x = sint * SIN(rota)
- z = sint * COS(rota)
- lat = ASIN(z) * !RADEG
- lon = ATAN(x,y) * !RADEG + lon0
- lon = lon + (lon LT -180.) * 360.
- lon = lon - (lon GT 180.) * 360.
- PLOTS, lon, lat, COLOR=color, THICK=2
- end
-
- ;----------------------------------------------------------------------------
- ;
- ; PURPOSE Connect two points, in the form of [lon, lat] with
- ; a great circle.
- ;
- pro cir_2p, $
- p1, $ ; IN: first point
- p2 ; IN: second point
-
- COMMON map_demo_com, projs, iproj, map_window, $
- lat0, lon0, rot0, do_elev, do_cont, cir , drawable, lat_slider, $
- lon_slider, sat_params, sat_base, rot_slider, $
- city_pos, elev_data, last_p, iso, $
- all_cities, scale, interpolation, do_rivers, $
- do_political, MenuButtons, MenuItems, ElevColor, $
- sText, wText, city_base, scale_txt, groupBase, SavedColors, MousePress
-
-
- r_earth = 6371.007 ; Constants: Mean radius of earth, KM
- km_mile = 0.621 ; Km per mile
-
- p1r = p1 * !dtor ;To radians
- p2r = p2 * !dtor
-
- twopi = 2 * !pi
- dlon = twopi + p2r(0) - p1r(0)
- while (dlon GT !pi) do dlon = dlon - twopi ;to -pi to +pi
-
- ; Compute the Great Circle Distance (in KM).
- cosd = SIN(p1r(1))*SIN(p2r(1)) + COS(p1r(1))*COS(p2r(1))*COS(dlon)
- dst = r_earth * ACOS(cosd)
-
- ; Transform the spherical coordinates (long. lat.) to cartesian (x, y, z).
- lon = [p1r(0), p2r(0)]
- lat = [p1r(1), p2r(1)]
- x = COS(lat) * SIN(lon)
- y = COS(lat)* COS(lon)
- z = SIN(lat)
-
- ; Compute the Plane containing center of earth and the points.
- a = z(0) * y(1) - y(0) * z(1)
- b = z(1) * x(0) - x(1) * z(0) ; aX + bY = Z
-
- elon0 = -ATAN(b/a) ; Compute the equatorial crossing location.
- rot = ATAN(tan(lat(1)) / SIN(lon(1) - elon0))
- rot = 90 - rot * !radeg
-
- cir.lon0 = !RADEG * elon0
- cir.rot = rot
-
- str1 = STRING(dst, dst*km_mile, $
- FORMAT="('Distance: ',i5,'km, ', i5, 'mi')")
- str2 = STRING(cir.rot, cir.lon0, $
- FORMAT="('Incl.: ',f6.1, ', Eq. cross.: ',F5.1)")
- sText.text[9] = str1
- sText.text[10] = str2
- putTips, sText, wText[1], ['dist1', 'dist2'], [0,1]
-
- cir.color = cir.color+1
-
- if (cir.color GE 10) then cir.color = 4 ;use color indices 4 to 9 for gt circl
- drawcirc, cir.rot, cir.lon0, cir.color ; Draw the great circle
- PLOTS, p1(0), p1(1), psym=5 ; and mark the points.
- PLOTS, p2(0), p2(1), psym=5
-
- end
-
- ;----------------------------------------------------------------------------
- ;
- ; PURPOSE Mark the Ith city and return [lon, lat]
- ;
- function city_mark, $
- i, $ ; IN: City index
- COLOR=color ; IN: Color index
-
- COMMON map_demo_com
-
- lon = city_pos.pos(1,i)
- lat = city_pos.pos(0,i)
-
- p = CONVERT_COORD(lon, lat, /DATA, /TO_DEVICE)
-
- if (FINITE(p(0)) EQ 0) then RETURN, p
-
- PLOTS, p(0), p(1), /DEVICE, PSYM=4, NOCLIP=0
-
- if (N_ELEMENTS(color) EQ 0) then COLOR=1
-
- XYOUTS, p(0), p(1)- 3*!D.Y_CH_SIZE/4, $
- /DEVICE, city_pos.names(i), $
- NOCLIP=0, ALIGNMENT=0.5, COLOR=color
-
- RETURN, [lon, lat]
- end
-
- ;----------------------------------------------------------------------------
- ;
- ; PURPOSE Draw the map
- ;
- pro map_demo_draw
-
- COMMON map_demo_com
-
- WSET, map_window
-
- lat1 = lat0 ; Take care of special cases:
- scale1 = scale
-
- if (STRPOS(projs(iproj), "Conic") GE 0) then begin
- if (scale1 EQ 0) then scale1 = 50e6 ; force default scaling.
- scale1 = scale1 < 100e6
- lat1 = lat1 < 60 > (-60) ; Stay away from the poles.
- minlat = 20
- if (ABS(lat1) LT minlat) then lat1 = ([minlat, -minlat])(lat1 LT 0)
- if (rot0 NE 0) then begin ; Force 0 rotation for conics
- rot0 = 0.0
- WIDGET_CONTROL, rot_slider, SET_VALUE=0.0
- endif
- endif
-
- if (projs(iproj) EQ 'TransverseMercator') then begin
- if (scale1 EQ 0) then scale1 = 50e6 ; Set default scaling.
- scale1 = scale1 < 100e6 ;maximum scale
- lat1 = lat1 > (-50) < 50 ; Stay away from poles.
- endif
-
- if (lat1 NE lat0) then $ ;Update slider if we fudged things
- WIDGET_CONTROL, lat_slider, SET_VALUE=lat1
-
- lat0 = lat1
-
- t0 = systime(1) ; Get the starting time.
-
- map_set, lat1, lon0, rot0, $ ;Draw basic projection
- PROJ = iproj, GRID=0, COLOR=1, $
- sat_p = sat_params, $
- ISOTROPIC=iso, scale=scale1
-
- ; print, !map.ll_box, format='(4f10.2)'
-
- wWarningBase = 0
-
- ; Load elevations ****
- if ( (do_elev NE 0) AND (N_ELEMENTS(elev_data) LE 2) ) then begin ; 1st time?
- wWarningBase = WIDGET_BASE(TITLE='Warning', /COLUMN)
- wWarning1Label = WIDGET_LABEL(wWarningBase, $
- VALUE='Warping elevation data to maps can')
- wWarning2Label = WIDGET_LABEL(wWarningBase, $
- VALUE='require a significant amount of time.')
-
- WIDGET_CONTROL, wWarningBase, /REALIZE
-
- file = filepath('worldelv.dat', $
- SUBDIR=['examples','data'])
-
- OPENR,unit, /GET_LUN, file, ERROR=i
-
- if (i LT 0) then begin
- a = DIALOG_MESSAGE(['Elevation data file', $
- file, 'not found'], /ERROR)
- do_elev = 0 ;Still have no elevations
- endif else begin ;we've found the file
- elev_data = BYTARR(360, 360, /NOZERO)
- READU, unit, elev_data
- CLOSE, unit
- FREE_LUN, unit
- elev_data = bytscl(elev_data, TOP=!d.table_size - ElevColor - 1, $
- MAX=255, MIN=0) + $
- byte(ElevColor) > byte(ElevColor + 1b)
- endelse
- endif ; of load elevation data
-
- t1 = systime(1)
-
- ; Draw the elevation data.
-
- if ((do_elev NE 0) AND (N_ELEMENTS(elev_data) GT 2)) then begin
- nlon = ([0,180, 360, 360])(do_elev) ;Low, Medium and High resolutions
- nlat = ([0, 90, 180, 180])(do_elev)
-
- lat_del = 180 / nlat
- lon_del = 360 / nlon
- lat_0 = -90. & lat1 = 90. - lat_del
- lon_0 = 0. & lon_1 = 360. - lon_del
- tmp = REBIN(elev_data, nlon, nlat,/SAMPLE)
-
- if (!map.ll_box(0) NE !map.ll_box(2)) then begin ; Clip the latitude.
- i0 = floor((!map.ll_box(0)+90) / lat_del) ;First bin
- i1 = ceil((!map.ll_box(2)+90) / lat_del) < (nlat -1) ;Last bin
- tmp = tmp(*, i0:i1 )
- lat_0 = lat_del * i0 -90.
- lat1 = lat_del * i1 -90.
- endif
-
- if (!map.ll_box(1) NE !map.ll_box(3)) then begin ; Clip the longitude.
- i0 = floor(!map.ll_box(1) / lon_del) ;First bin
- i1 = ceil( !map.ll_box(3) / lon_del) ;Last bin
- j0 = i0
- if (j0 LT 0) then j0 = j0 + nlon
- if (j0 NE 0) then tmp = shift(tmp, -j0, 0)
- n = i1 - i0 + 1
- if (n LT nlon) then tmp = tmp(0:n-1, *)
- lon_0 = i0 * lon_del
- lon_1 = i1 * lon_del
- endif
-
- if (interpolation) then begin
- TV, MAP_PATCH(tmp, LON0=lon_0, LON1=lon_1, $ ;Object interpolation
- LAT0=lat_0, LAT1=lat1, $
- XSTART=x0, YSTART=y0), x0, y0
- endif else begin
- TV, MAP_IMAGE(tmp, $ ;Image interpolation
- LONMIN=lon_0, LONMAX=lon_1, LATMIN=lat_0, LATMAX=lat1, $
- /BILINEAR, COMPRESS= ([0,4, 4,2,1])(do_elev), x0, y0), $
- x0, y0
- endelse
- endif ; of Do_elev
-
- if (wWarningBase NE 0) then WIDGET_CONTROL, wWarningBase, /DESTROY
-
- t1 = systime(1) - t1 ; Get the executon time.
-
- if (do_elev NE 0) then $ ; Don't do both continents and elevation.
- i = do_cont < 1 $
- else i = do_cont
-
- map_horizon, COLOR=([1,1,4])(i), FILL=i EQ 2 ; Blue horizon
-
- if (i EQ 1) then map_continents, COLOR=1 ;Line continents
- if (i EQ 2) then map_continents, COLOR=5, /fill ;Filled continents
-
- map_grid, latdel = 10, londel = 10, COLOR=3
-
- if (do_rivers) then map_continents, /RIVER, COLOR=4
- if (do_political) then map_continents, /COUNTRIES, /USA, COLOR=1
- if ((do_cont GE 2) OR (do_elev NE 0)) then CCOLOR=0 else CCOLOR=1
- if (all_cities) then for i=0, N_ELEMENTS(city_pos.names)-1 do $
- p = city_mark(i, COLOR=ccolor)
-
- if (do_elev NE 0) then begin ;Execution time
- t = t1 + systime(1)-t0
- endif else begin
- t = systime(1)-t0
- endelse
-
- estr='Time =' + STRING(t, FORMAT='(F6.1)')+ ' seconds' ;Display exec time
- sText.text[7] = estr
-
- putTips, sText, wText[1], ['selecto','time1'], [0,1]
- end
-
- ;----------------------------------------------------------------------------
- ;
- ; PURPOSE Main event handler.
- ;
- pro d_map_event, $
- event ; IN: event structure
-
- COMMON colors, r_orig, g_orig, b_orig, r_curr, g_curr, b_curr
- COMMON map_demo_com
-
-
- if (TAG_NAMES(event, /STRUCTURE_NAME) EQ $ ;Was application closed?
- 'WIDGET_KILL_REQUEST') then begin
- WIDGET_CONTROL, event.top, /DESTROY
- RETURN
- endif
-
- WIDGET_CONTROL, event.id, GET_UVALUE=eventval
- s = SIZE(eventval)
- WSET, map_window
-
- if (event.id EQ drawable) then begin ;Mouse event in drawable
- ; Get inverse transform (lat, lon):
- p = CONVERT_COORD(event.x, event.y, /DEVICE, /TO_DATA)
-
- if (FINITE(p(0)) EQ 0) then begin ;IDL 5.0 returns NaN for unmappable pnts
- off_map:
- sText.text[6] = '<Off map>'
- putTips, sText, wText[1], ['locat'], [2]
- RETURN
- endif
-
- if (event.press NE 0) then begin ; Save location of button press events
- MousePress = [event.x, event.y]
- goto, set_ll
- endif
-
- if (event.release EQ 0) then begin ;If release is 0, its a motion event
- sText.text[6] = STRING(p(0), p(1), $
- FORMAT= "('Lon: ',f7.1, ', Lat: ', f6.1)")
- putTips, sText, wText[1], ['locat'], [2]
- RETURN
- endif
-
- ; If we get here, its a drag event. Put a hysteresis on the drag so that
- ; it's not mistaken for a smudged click.
- if (ABS(event.x-MousePress[0]) + $
- ABS(event.y NE MousePress[1]) GE 4) then begin
- q = CONVERT_COORD(MousePress, /DEVICE, /TO_DATA)
- if (FINITE(q(0)) EQ 0) then return
- lat0 = lat0 + (q(1)-p(1)) ;Get new center of projection
- if (lat0 GT 180.) then lat0 = lat0 - 360.
- if (lat0 LT -180.) then lat0 = lat0 + 360.
- if (lat0 GT 90.) then lat0 = 180.-lat0
- if (lat0 LT -90.) then lat0 = -180.-lat0
-
- lon0 = lon0 + (q(0)-p(0)) + 360.
-
- while (lon0 GT 180) do lon0 = lon0 - 360.
- while (lon0 LT -180) do lon0 = lon0 + 360.
-
- WIDGET_CONTROL, lat_slider, SET_VALUE=lat0
- WIDGET_CONTROL, lon_slider, SET_VALUE=lon0
- goto, draw_it
- endif ; of Drag.
-
- RETURN
-
- set_ll:
- sText.text[6] = STRING(p(0), p(1), $
- FORMAT= "('Lon: ',f7.1, ', Lat: ', f6.1)")
- putTips, sText, wText[1], ['locat'], [2]
-
- if (cir.llflag EQ 2) then begin ;Marked 2nd point for gt circle?
- cir_2p, cir.ll, p(0:1)
- cir.llflag = 0
- endif
-
- if (cir.llflag EQ 1) then begin ;Marked 1st pnt for gt circle?
- sText.text[7] = 'Mark second point.'
- putTips, sText, wText[1], ['void','time1'], [0,1]
- cir.ll = p(0:1)
- cir.llflag = 2
- endif
-
- RETURN
-
- endif ;Cursor hit on map
-
- if (STRMID(eventval, 0, 1) EQ '|') then begin ; If '|' in value, its a menu
- ev = STRMID(eventval, 1, 100) ; get event name by stripping off the '|'
-
- if (ev EQ 'File|Quit') then begin
- WIDGET_CONTROL, event.top, /DESTROY
- RETURN
- endif else if (ev EQ 'Edit|Reset') then begin ;Reset to initial values
- lat0 = 0.
- lon0 = 0.
- rot0 = 0.
- WIDGET_CONTROL, LAT_SLIDER, SET_VALUE=lat0
- WIDGET_CONTROL, LON_SLIDER, SET_VALUE=lon0
- WIDGET_CONTROL, ROT_SLIDER, SET_VALUE=rot0
- endif else if (ev EQ 'About|About Maps') then begin
- if (Xregistered('XDisplayfile') NE 0) then RETURN
- XDisplayfile, filepath("map_demo.txt", $
- SUBDIR=['examples','demo','demotext']), $
- DONE_BUTTON='Done', $
- TITLE="About the Map Demo", $
- GROUP=event.top, $
- WIDTH=68, HEIGHT=18
- RETURN
-
- endif else if (STRPOS(ev, 'Continents') GT 0) then begin
- ; Toggle the continents/elevation choices..
- i = map_menu_choice(eventval, MenuItems, MenuButtons)
- do_cont = 0
- do_elev = 0
- if (i le 2) then do_cont = i else do_elev = i-2
- endif else if (STRPOS(ev, 'Interpolation') GT 0) then begin
- ; image and object interpolation choices
- interpolation = map_menu_choice(eventval, MenuItems, MenuButtons)
- if (do_elev EQ 0) then RETURN ; don't redraw unless elevations are on.
- endif else if STRPOS(ev, 'Rivers') GT 0 then begin
- do_rivers = MenuToggleState(event.id) ;New river state
- endif else if STRPOS(ev, 'Isotropy') GT 0 then begin ;New isotropic setting
- iso = MenuToggleState(event.id)
- endif else if STRPOS(ev, 'Boundaries') GT 0 then begin
- do_political = MenuToggleState(event.id) ;New political setting
- endif else if STRPOS(ev, 'View|Cities') EQ 0 then begin
- all_cities = MenuToggleState(event.id) ;New city setting
- endif else if (ev EQ 'Cities|Find') then begin
- if (WIDGET_INFO(city_base, /VALID) EQ 0) then begin
- ; Create the city finder widget.
- city_base = WIDGET_BASE(Title='Cities', /COLUMN, $
- EVENT_PRO='d_map_event', $
- GROUP_LEADER=event.top)
-
- wCityList = WIDGET_LIST(city_base, VALUE=city_pos.names, $
- YSIZE = 12, UVALUE="CITY_SELECT")
-
- wDismissButton = WIDGET_BUTTON(city_base, $
- VALUE='Dismiss', /NO_REL, $
- UVALUE='CITY_DISMISS')
-
- WIDGET_CONTROL, city_base, /REALIZE
- XMANAGER, "map_cities", city_base, $
- EVENT_HANDLER="d_map_event",$
- GROUP_LEADER = event.top
- endif $
- else WIDGET_CONTROL, city_base, /MAP ;Already mapped, just show it
- RETURN
-
- endif else if (ev EQ 'Cities|Mark All') then begin ;Mark all cities
- if ((do_cont GE 2) or (do_elev NE 0)) then begin
- CCOLOR = 0
- endif else begin
- CCOLOR = 1
- endelse
-
- for i = 0, N_ELEMENTS(city_pos.names)-1 do begin
- p = city_mark(i, COLOR=ccolor)
- endfor
- return
-
- endif else if (ev EQ 'Great Circles|Draw') then begin ;Draw great circle
- cir.color = cir.color+1
- if (cir.color GE 16) then cir.color = 4
- drawcirc, cir.rot, cir.lon0, cir.color
- RETURN
-
- endif else if (ev EQ 'Great Circles|Connect Two Points') then begin
- cir.llflag = 1 ;Expecting first point
- sText.text[7] = 'Mark first point.'
-
- putTips, sText, wText[1], ['void','time1'], [0,1]
- RETURN
-
- endif else print,'Unknown Menu Item: ', ev
-
- endif else case eventval of ;Must be a slider event
- "LAT_SLIDER": lat0 = event.value
- "LON_SLIDER": lon0 = event.value
- "ROT_SLIDER": rot0 = event.value
- "SALT" : sat_params(0) = 1.0 + event.value / 6371.; Sat altitude
- "SALPHA" : sat_params(1) = event.value
- "SBETA" : sat_params(2) = event.value
- "CITY_DISMISS": begin
- WIDGET_CONTROL, city_base, MAP=0
- RETURN
- endcase
-
- "CITY_SELECT": begin ; Draw the selected city.
- p = city_mark(event.index) ;The item selected
- if (FINITE(p(0))) then goto, set_ll
- goto, off_map
- endcase
-
- "SCALE": begin ;New map scale
- WIDGET_CONTROL, event.id, GET_VALUE=v
- scale = FLOAT(v(0))
- minmax = [1,400]
- if (scale NE 0) and $
- (scale LT minmax(0) or scale GT minmax(1)) then begin
- scale = scale > minmax(0) < minmax(1)
- WIDGET_CONTROL, event.id, SET_VALUE=STRTRIM(scale,2)
- endif
- scale = scale * 1.0e6 ;To millions
- endcase
-
- "PROJ": begin ;New projection
- iproj = event.index+1 ;New projection number
- if (last_p EQ iproj) then RETURN ; Nothing to do?
- last_p = iproj
-
- if (projs(iproj) EQ "Satellite") then begin
- ; Case of a satellite projection, open
- ; an new window that let select its parameters.
- slide_wid = 250
- sat_base = LONARR(5)
- sat_base(0) = $
- WIDGET_BASE(title='Satellite Projection Parameters', /COLUMN)
-
- sat_base(1) = $
- WIDGET_SLIDER(sat_base(0), XSIZE=slide_wid, $
- MINIMUM=100, MAXIMUM=15000, $
- VALUE=(sat_params(0)-1) * 6371., $
- TITLE='Altitude (Km)', $
- UVALUE="SALT")
-
- sat_base(2) = $
- WIDGET_SLIDER(sat_base(0), XSIZE=slide_wid, $
- MINIMUM=-89, MAXIMUM=89, $
- VALUE=sat_params(1), TITLE='Alpha (up)',$
- UVALUE="SALPHA")
-
- sat_base(3) = $
- WIDGET_SLIDER(sat_base(0), XSIZE=slide_wid, $
- MINIMUM=-180, MAXIMUM=180, $
- VALUE=sat_params(2), $
- TITLE='Beta (rotation)', $
- UVALUE="SBETA")
-
- WIDGET_CONTROL, sat_base(0), /REALIZE
-
- XMANAGER, "map_demo_satellite", sat_base(0), $
- EVENT_HANDLER="D_MAP_EVENT", $
- GROUP_LEADER=event.top
- RETURN
-
- endif else begin ;Not a satellite projection
- if (sat_base(0) NE 0) then begin ; Kill satellite base if active.
- if (WIDGET_INFO(sat_base(0),/valid)) then $
- WIDGET_CONTROL, sat_base(0),/DESTROY
- sat_base(0) = 0
- endif
- endelse ;Not satellite
- endcase ; of Projection
-
- else: MESSAGE, "Event user value not found " + eventval
-
- endcase
-
- draw_it: WIDGET_CONTROL, event.top, /HOURGLASS
- map_demo_draw ;********** Draw the map....
- end
-
- ;-----------------------------------------------------------------
- ;
- ; PURPOSE : cleanup procedure. restore colortable, destroy objects.
- ;
- pro d_map_Cleanup, $
- wTopBase ; IN: Top level base identifier
-
- COMMON map_demo_com
-
- TVLCT, SavedColors ; Restore the color table.
- if (WIDGET_INFO(groupBase, /VALID_ID)) then $
- WIDGET_CONTROL, groupBase, /MAP
- end ; of d_map_Cleanup
-
- ;----------------------------------------------------------------------------
- ;
- ; PURPOSE Main map procedure.
- ;
- pro d_map, $
- Image, $ ; IN: (opt) image warped around the
- ; projection that should be properly
- ; scaled.
- GROUP=GROUP, $ ; IN: (opt) Group leader identifier
- Xsize = Xsize, $ ; IN: (opt) X size of the viewing area.
- APPTLB=appTlb ; OUT: (opt) main procedure top level base ID
-
- COMMON map_demo_com
-
- ; Make sure that only one instance is active.
- if (XRegistered("d_map")) then RETURN
-
-
- if N_ELEMENTS(group) then groupbase = group else groupbase = 0L
-
- TVLCT, SavedColors, G, B, /GET ; save the current color table
- SavedColors = [[SavedColors],[G],[B]] ; save in a (n,3) array
-
- DEVICE, GET_SCREEN_SIZE = scrSize
- drawbase = startmes('Mapping Demo', GROUP=groupbase)
-
- if (N_ELEMENTS(image) GT 1) then begin ;image to warp over data provided?
- elev_data = image > 16b ; Bottom 16 colors are used for grids
- endif
-
- iproj = 2 ; orthographic
- last_p = -1
- if (N_ELEMENTS(xsize) EQ 0) then begin ; Size the viewing area to screen
- xsize = FIX(0.56 * scrSize(0))
- endif
-
- DEVICE, DECOMPOSED = 0 ; Set to a 8 bits (256 colors) display.
- list_ht = ([6,9])(xsize GE 400) ; List widget height for small screens.
-
- ysize = xsize * 4 / 5 ; Initialize working variables.
- sliderwidth = 200 < (xsize/3)
- lat0 = 0
- lon0 = 0
- rot0 = 0
- do_cont = 2 ;Initial default = fill continents
- do_elev = 0
- do_rivers = 0
- do_political = 0
- iso = 1
- all_cities = 0
- scale = 0.0
- interpolation = 0
- city_base = 0L
- elevColor = 10 ;First color used for elevations
- !p.multi=0
-
- cir = { CIRCLE_PARAMS, $ ;Great circle object
- base : 0L, lon0 : 0.0, rot : 0.0, color : 4, $
- ll : [0., 0.], llflag : 0 }
-
- sat_params = [ 1.2, 0, 0] ;Salt, salpha, sbeta = Initial satellite params
-
- sat_base = LONARR(5)
- sText = getTips(filepath('map_demo.tip', $ ; Get the tips.
- SUBDIR=['examples','demo', 'demotext']))
-
-
- map_demoBase = WIDGET_BASE(TITLE="Mapping", $ ;Main base, not mapped yet
- MAP=0, $
- /TLB_KILL_REQUEST_EVENTS, $
- TLB_FRAME_ATTR=1, $
- MBAR=bar_base, /COLUMN, GROUP=groupbase)
-
- MenuItems = ['1File', '2Quit', $
- '1Edit', '2Reset', $
- '1View', $
- '1Continents', '0None', '0Outlines', '4Fill', $
- '0Low Res Elevations', '0Medium Res', '2High Res', $
- '1Interpolation', '4Image', '2Object', $
- '0Rivers (Off)', $
- '0Boundaries (Off)', $
- '0Cities (Off)', $
- '2Isotropy (On )', $
- '1Cities', '0Mark All', '2Find', $
- '1Great Circles', '0Connect Two Points', '2Draw', $
- '1About', '2About Maps']
-
- MenuCreate, MenuItems, MenuButtons, Bar_base ; Create the menu bar.
-
- if (N_ELEMENTS(projs) EQ 0) then begin ; Define projection names.
- resolve_routine, 'map_set' ; Cause we call map_proj_info first.
- map_proj_info, PROJ_NAMES=projs
- endif
-
-
- wSubBase = WIDGET_BASE(map_demobase, /ROW) ;Create the column sub base.
- l_base = WIDGET_BASE(wSubBase, /COLUMN) ; Create the left side widgets.
-
-
- wJunk = WIDGET_BASE(l_base, /COLUMN, /FRAME)
- wProjLabel = WIDGET_LABEL(wJunk, VALUE='Projection')
- p_list = WIDGET_LIST(wJunk, VALUE=projs(1:*), $ ;projection list
- YSIZE=list_ht, UVALUE='PROJ')
-
- lon_slider = WIDGET_SLIDER(l_base, XSIZE = sliderwidth, $
- MINIMUM = -180, MAXIMUM = 180, VALUE=lon0, $
- TITLE = 'Center Longitude', uvalue = "LON_SLIDER")
- lat_slider = WIDGET_SLIDER(l_base, XSIZE = sliderwidth, $
- MINIMUM = -90, MAXIMUM = 90, VALUE=lat0, $
- TITLE = 'Center Latitude', uvalue = "LAT_SLIDER")
- rot_slider = WIDGET_SLIDER(l_base, XSIZE = sliderwidth, $
- MINIMUM = -90, MAXIMUM = 90, VALUE=rot0, $
- TITLE = 'Rotation', uvalue = "ROT_SLIDER")
- wJunk = WIDGET_BASE(l_base, /ROW)
- wScale1Label = WIDGET_LABEL(wJunk, VALUE="Scale ")
- scale_txt = WIDGET_TEXT(wJunk, XSIZE=10, YSIZE=1, $
- VALUE='0.0', $
- /EDITABLE, UVALUE="SCALE")
- wScale2Label = WIDGET_LABEL(wJunk, VALUE="Million : 1")
-
- if (N_ELEMENTS(city_pos) LE 0) then begin ;Input City data base if 1st time
- file = filepath('cities.dat', $
- SUBDIR=['examples','demo','demodata'])
- OPENR, unit, file, /GET_LUN, ERROR=i
-
- if (i LT 0) then begin
- a = DIALOG_MESSAGE(['City data file', file, 'not found'],/ERROR)
- i = 4
- city_names = STRARR(i) ;Fake it
- city_pos = FLTARR(2,i)
- endif else begin
- i = (fstat(unit)).size/12 ;Approx number of cities
- city_names = STRARR(i)
- city_pos = FLTARR(2,i)
- i = 0
- x=0. & y=0. & z = ''
-
- while (NOT Eof(unit)) do begin
- READF,unit, x, y, z
- city_names(i) = z
- city_pos(0,i) = x ;Latitude
- city_pos(1,i) = y
- i = i + 1
- endwhile
- CLOSE, unit
- FREE_LUN, unit
-
- city_pos = city_pos(*,0:i-1) ;correct for file being in degrees.minutes
- icity = FIX(city_pos)
- fcity = city_pos - FIX(city_pos) ;Decimal fractions
- city_pos = icity + (fcity * (100./60.)) ; Convert minutes to 100ths.
- endelse
-
- city_pos = { CITY_POS, $
- names : STRTRIM(city_names(0:i-1),2), $
- pos : city_pos }
- endif
-
- r_base = WIDGET_BASE(wSubBase, /COLUMN) ; Create the right side widgets.
- ;
- drawable = WIDGET_DRAW(r_base, XSIZE=xsize, YSIZE=ysize, $ ; view area.
- RETAIN=2, /BUTTON_EVENTS, /MOTION_EVENTS)
-
- wStatusBase = WIDGET_BASE(map_demobase, MAP=0, /ROW) ; Create tips texts.
-
- nWidgets = 2
- wText = LONARR(nWidgets)
- widTips, wStatusBase, sText.text, XSIZE=36, YSIZE=3, NWIDGETS=nWidgets, wText
-
- WIDGET_CONTROL, map_demobase, /REALIZE, /HOURGLASS
-
- appTlb = map_demobase ; Return top level base into APPTLB variable.
-
- WIDGET_CONTROL, drawable, GET_VALUE=map_window ; Get the window ID.
-
- sizeTips, map_demobase, wText, wStatusBase
-
- sText.text[7] = 'Move Mouse on map'
- sText.text[8] = 'for inverse transforms'
-
- putTips, sText, wText[1], ['time1', 'time2'], [0,1]
-
- WIDGET_CONTROL, p_list, SET_LIST_SELECT=1
-
- WSET, map_window
- map_demo_color, ElevColor ; Load our color tables.
- map_demo_draw ; Draw the first map.
-
- WIDGET_CONTROL, drawbase, /DESTROY ; Destroy the startup window.
- WIDGET_CONTROL, map_demoBase, MAP=1 ; Map the top level base.
- XMANAGER, "d_map", map_demobase, $ ; Register with XMANAGER.
- CLEANUP='d_map_cleanup', $
- /NO_BLOCK
-
- WIDGET_CONTROL, map_demobase, HOURGLASS=0
- elev_data = 0 ; Free up some memory.
- end ; of main procedure d_map
-